home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / dev / lang / Python151_Src.lha / Python1.5_Source / Modules / cmathmodule.c < prev    next >
C/C++ Source or Header  |  1998-01-26  |  6KB  |  327 lines

  1. /* Complex math module */
  2.  
  3. /* much code borrowed from mathmodule.c */
  4.  
  5. #include "Python.h"
  6.  
  7. #include "mymath.h"
  8.  
  9. #include "protos/cmathmodule_protos.h"
  10.  
  11. #ifdef i860
  12. /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
  13. #undef HUGE_VAL
  14. #endif
  15.  
  16. #ifdef HUGE_VAL
  17. #define CHECK(x) if (errno != 0) ; \
  18.     else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
  19.     else errno = ERANGE
  20. #else
  21. #define CHECK(x) /* Don't know how to check */
  22. #endif
  23.  
  24. #ifndef M_PI
  25. #define M_PI (3.141592653589793239)
  26. #endif
  27.  
  28. /* First, the C functions that do the real work */
  29.  
  30. /* constants */
  31. static Py_complex c_1 = {1., 0.};
  32. static Py_complex c_half = {0.5, 0.};
  33. static Py_complex c_i = {0., 1.};
  34. static Py_complex c_i2 = {0., 0.5};
  35. #if 0
  36. static Py_complex c_mi = {0., -1.};
  37. static Py_complex c_pi2 = {M_PI/2., 0.};
  38. #endif
  39.  
  40. /* forward declarations */
  41. staticforward Py_complex c_log();
  42. staticforward Py_complex c_prodi();
  43. staticforward Py_complex c_sqrt();
  44.  
  45. #include "protos/cmathmodule_protos.h"
  46.  
  47. static Py_complex c_acos(x)
  48.     Py_complex x;
  49. {
  50.     return c_neg(c_prodi(c_log(c_sum(x,c_prod(c_i,
  51.             c_sqrt(c_diff(c_1,c_prod(x,x))))))));
  52. }
  53.  
  54. static Py_complex c_acosh(x)
  55.     Py_complex x;
  56. {
  57.     return c_log(c_sum(x,c_prod(c_i,
  58.             c_sqrt(c_diff(c_1,c_prod(x,x))))));
  59. }
  60.  
  61. static Py_complex c_asin(x)
  62.     Py_complex x;
  63. {
  64.     return c_neg(c_prodi(c_log(c_sum(c_prod(c_i,x),
  65.             c_sqrt(c_diff(c_1,c_prod(x,x)))))));
  66. }
  67.  
  68. static Py_complex c_asinh(x)
  69.     Py_complex x;
  70. {
  71.     return c_neg(c_log(c_diff(c_sqrt(c_sum(c_1,c_prod(x,x))),x)));
  72. }
  73.  
  74. static Py_complex c_atan(x)
  75.     Py_complex x;
  76. {
  77.     return c_prod(c_i2,c_log(c_quot(c_sum(c_i,x),c_diff(c_i,x))));
  78. }
  79.  
  80. static Py_complex c_atanh(x)
  81.     Py_complex x;
  82. {
  83.     return c_prod(c_half,c_log(c_quot(c_sum(c_1,x),c_diff(c_1,x))));
  84. }
  85.  
  86. static Py_complex c_cos(x)
  87.     Py_complex x;
  88. {
  89.     Py_complex r;
  90.     r.real = cos(x.real)*cosh(x.imag);
  91.     r.imag = -sin(x.real)*sinh(x.imag);
  92.     return r;
  93. }
  94.  
  95. static Py_complex c_cosh(x)
  96.     Py_complex x;
  97. {
  98.     Py_complex r;
  99.     r.real = cos(x.imag)*cosh(x.real);
  100.     r.imag = sin(x.imag)*sinh(x.real);
  101.     return r;
  102. }
  103.  
  104. static Py_complex c_exp(x)
  105.     Py_complex x;
  106. {
  107.     Py_complex r;
  108.     double l = exp(x.real);
  109.     r.real = l*cos(x.imag);
  110.     r.imag = l*sin(x.imag);
  111.     return r;
  112. }
  113.  
  114. static Py_complex c_log(x)
  115.     Py_complex x;
  116. {
  117.     Py_complex r;
  118.     double l = hypot(x.real,x.imag);
  119.     r.imag = atan2(x.imag, x.real);
  120.     r.real = log(l);
  121.     return r;
  122. }
  123.  
  124. static Py_complex c_log10(x)
  125.     Py_complex x;
  126. {
  127.     Py_complex r;
  128.     double l = hypot(x.real,x.imag);
  129.     r.imag = atan2(x.imag, x.real)/log(10.);
  130.     r.real = log10(l);
  131.     return r;
  132. }
  133.  
  134. static Py_complex c_prodi(x)
  135.      Py_complex x;
  136. {
  137.     Py_complex r;
  138.     r.real = -x.imag;
  139.     r.imag = x.real;
  140.     return r;
  141. }
  142.  
  143. static Py_complex c_sin(x)
  144.     Py_complex x;
  145. {
  146.     Py_complex r;
  147.     r.real = sin(x.real)*cosh(x.imag);
  148.     r.imag = cos(x.real)*sinh(x.imag);
  149.     return r;
  150. }
  151.  
  152. static Py_complex c_sinh(x)
  153.     Py_complex x;
  154. {
  155.     Py_complex r;
  156.     r.real = cos(x.imag)*sinh(x.real);
  157.     r.imag = sin(x.imag)*cosh(x.real);
  158.     return r;
  159. }
  160.  
  161. static Py_complex c_sqrt(x)
  162.     Py_complex x;
  163. {
  164.     Py_complex r;
  165.     double s,d;
  166.     if (x.real == 0. && x.imag == 0.)
  167.         r = x;
  168.     else {
  169.         s = sqrt(0.5*(fabs(x.real) + hypot(x.real,x.imag)));
  170.         d = 0.5*x.imag/s;
  171.         if (x.real > 0.) {
  172.             r.real = s;
  173.             r.imag = d;
  174.         }
  175.         else if (x.imag >= 0.) {
  176.             r.real = d;
  177.             r.imag = s;
  178.         }
  179.         else {
  180.             r.real = -d;
  181.             r.imag = -s;
  182.         }
  183.     }
  184.     return r;
  185. }
  186.  
  187. static Py_complex c_tan(x)
  188.     Py_complex x;
  189. {
  190.     Py_complex r;
  191.     double sr,cr,shi,chi;
  192.     double rs,is,rc,ic;
  193.     double d;
  194.     sr = sin(x.real);
  195.     cr = cos(x.real);
  196.     shi = sinh(x.imag);
  197.     chi = cosh(x.imag);
  198.     rs = sr*chi;
  199.     is = cr*shi;
  200.     rc = cr*chi;
  201.     ic = -sr*shi;
  202.     d = rc*rc + ic*ic;
  203.     r.real = (rs*rc+is*ic)/d;
  204.     r.imag = (is*rc-rs*ic)/d;
  205.     return r;
  206. }
  207.  
  208. static Py_complex c_tanh(x)
  209.     Py_complex x;
  210. {
  211.     Py_complex r;
  212.     double si,ci,shr,chr;
  213.     double rs,is,rc,ic;
  214.     double d;
  215.     si = sin(x.imag);
  216.     ci = cos(x.imag);
  217.     shr = sinh(x.real);
  218.     chr = cosh(x.real);
  219.     rs = ci*shr;
  220.     is = si*chr;
  221.     rc = ci*chr;
  222.     ic = si*shr;
  223.     d = rc*rc + ic*ic;
  224.     r.real = (rs*rc+is*ic)/d;
  225.     r.imag = (is*rc-rs*ic)/d;
  226.     return r;
  227. }
  228.  
  229.  
  230. /* And now the glue to make them available from Python: */
  231.  
  232. static PyObject *
  233. math_error()
  234. {
  235.     if (errno == EDOM)
  236.         PyErr_SetString(PyExc_ValueError, "math domain error");
  237.     else if (errno == ERANGE)
  238.         PyErr_SetString(PyExc_OverflowError, "math range error");
  239.     else    /* Unexpected math error */
  240.         PyErr_SetFromErrno(PyExc_ValueError); 
  241.     return NULL;
  242. }
  243.  
  244. static PyObject *
  245. math_1(args, func)
  246.     PyObject *args;
  247.     Py_complex (*func) Py_FPROTO((Py_complex));
  248. {
  249.     Py_complex x;
  250.     if (!PyArg_ParseTuple(args, "D", &x))
  251.         return NULL;
  252.     errno = 0;
  253.     PyFPE_START_PROTECT("complex function", return 0)
  254.     x = (*func)(x);
  255.     PyFPE_END_PROTECT(x)
  256.     CHECK(x.real);
  257.     CHECK(x.imag);
  258.     if (errno != 0)
  259.         return math_error();
  260.     else
  261.         return PyComplex_FromCComplex(x);
  262. }
  263.  
  264. #ifdef HAVE_PROTOTYPES
  265. #define FUNC1(stubname, func) \
  266.     static PyObject * stubname(PyObject *self, PyObject *args) { \
  267.         return math_1(args, func); \
  268.     }
  269. #else /* !HAVE_PROTOTYPES */
  270. #define FUNC1(stubname, func) \
  271.     static PyObject * stubname(self, args) PyObject *self, *args; { \
  272.         return math_1(args, func); \
  273.     }
  274. #endif
  275.  
  276. FUNC1(cmath_acos, c_acos)
  277. FUNC1(cmath_acosh, c_acosh)
  278. FUNC1(cmath_asin, c_asin)
  279. FUNC1(cmath_asinh, c_asinh)
  280. FUNC1(cmath_atan, c_atan)
  281. FUNC1(cmath_atanh, c_atanh)
  282. FUNC1(cmath_cos, c_cos)
  283. FUNC1(cmath_cosh, c_cosh)
  284. FUNC1(cmath_exp, c_exp)
  285. FUNC1(cmath_log, c_log)
  286. FUNC1(cmath_log10, c_log10)
  287. FUNC1(cmath_sin, c_sin)
  288. FUNC1(cmath_sinh, c_sinh)
  289. FUNC1(cmath_sqrt, c_sqrt)
  290. FUNC1(cmath_tan, c_tan)
  291. FUNC1(cmath_tanh, c_tanh)
  292.  
  293.  
  294. static PyMethodDef cmath_methods[] = {
  295.     {"acos", cmath_acos, 1},
  296.     {"acosh", cmath_acosh, 1},
  297.     {"asin", cmath_asin, 1},
  298.     {"asinh", cmath_asinh, 1},
  299.     {"atan", cmath_atan, 1},
  300.     {"atanh", cmath_atanh, 1},
  301.     {"cos", cmath_cos, 1},
  302.     {"cosh", cmath_cosh, 1},
  303.     {"exp", cmath_exp, 1},
  304.     {"log", cmath_log, 1},
  305.     {"log10", cmath_log10, 1},
  306.     {"sin", cmath_sin, 1},
  307.     {"sinh", cmath_sinh, 1},
  308.     {"sqrt", cmath_sqrt, 1},
  309.     {"tan", cmath_tan, 1},
  310.     {"tanh", cmath_tanh, 1},
  311.     {NULL,        NULL}        /* sentinel */
  312. };
  313.  
  314. void
  315. initcmath()
  316. {
  317.     PyObject *m, *d, *v;
  318.     
  319.     m = Py_InitModule("cmath", cmath_methods);
  320.     d = PyModule_GetDict(m);
  321.     PyDict_SetItemString(d, "pi",
  322.                  v = PyFloat_FromDouble(atan(1.0) * 4.0));
  323.     Py_DECREF(v);
  324.     PyDict_SetItemString(d, "e", v = PyFloat_FromDouble(exp(1.0)));
  325.     Py_DECREF(v);
  326. }
  327.